﻿using Hx.ADSyncPlatform.SSO.Common;
using Hx.ADSyncPlatform.SSO.Config;
using Hx.ADSyncPlatform.SSO.Model;
using Hx.ADSyncPlatform.SSO.Response;
using RestSharp;
using System;

namespace Hx.ADSyncPlatform.SSO.Request
{
    public class AuthRequest
    {
        protected AuthConfig config;
        protected AuthSource source;

        public AuthRequest(AuthConfig config, AuthSource source)
        {
            this.config = config;
            this.source = source;
        }

        /// <summary>
        /// 生成AuthorizeUrl 返回给应用前端
        /// </summary>
        /// <param name="targetUrl">应用前端的重定向地址，比如/user/profile 登陆成功后回以redirect_uri参数附加在url上</param>
        /// <returns></returns>
        public string GenerateAuthorizeUrl(string targetUrl = null)
        {
            string targetPart = "";
            if (targetUrl != null) targetPart = $"&target_uri={targetUrl}";
            string authorizeUrl = $"{source.Host}/{source.AuthorizeURL}?client_id={config.ClientId}&response_type=code&redirect_uri={config.Callback}&{targetPart}";
            return authorizeUrl;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected string accessTokenUrl(string code)
        {
            string accessTokenUrl = $"{source.Host}/{source.AccessTokenURL}?client_id={config.ClientId}&client_secret={config.Secret}&code={code}&redirect_uri={config.Callback}";
            return accessTokenUrl;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected string userInfoUrl(string access_token)
        {
            string userInfoUrl = $"{source.Host}/{source.UserInfoURL}?access_token={access_token}";
            return userInfoUrl;
        }

        protected string logoutUrl(string redirectUrl)
        {
            string redirectPart = "";
            if (string.IsNullOrWhiteSpace(redirectUrl)) redirectUrl = source.CallBackHost;
            redirectPart = $"?redirect_url={redirectUrl}";
            string logoutUrl = $"{source.Host}/{source.LogoutURL}{redirectPart}";
            return logoutUrl;
        }


        protected void CheckResponse(bool hasError, Exception ex)
        {
            if (hasError)
            {
                if (ex != null) throw ex;
                throw new AuthException("SSO登陆产生错误");
            }

        }
        internal AuthToken GetAccessToken(string code)
        {
            var client = new RestClient();
            var request = new RestRequest(this.accessTokenUrl(code), DataFormat.Json);
            var res = client.Get(request);
            this.CheckResponse(!res.IsSuccessful, res.ErrorException);
            string jsonString = res.Content;
            int endIndex = jsonString.Length - 1;
            if (jsonString.Contains("&"))
            {
                endIndex = jsonString.IndexOf("&");
            }
            string accessToken = jsonString.Substring("access_token".Length + 1, endIndex - "access_token".Length - 1);

            AuthToken authToken = new AuthToken() { AccessToken = accessToken };
            return authToken;



        }

        internal AuthUser GetUserInfo(AuthToken auth)
        {
            var client = new RestClient();
            var request = new RestRequest(this.userInfoUrl(auth.AccessToken), DataFormat.Json);
            var res = client.Get<AuthUser>(request);
            if (res.IsSuccessful) this.CheckResponse(!res.IsSuccessful, res.ErrorException);
            AuthUser authUser = res.Data;

            return authUser;
        }

        /// <summary>
        /// code换取token
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public AuthResponse<AuthUser> Login(string code)
        {

            try
            {
                Console.WriteLine("AuthToken开始----");
                AuthToken authToken = this.GetAccessToken(code);
                Console.WriteLine($"AuthToken获取完成---【{authToken.AccessToken}】");
                AuthUser authUser = this.GetUserInfo(authToken);
                Console.WriteLine("AuthUser获取完成");
                return new AuthResponse<AuthUser>()
                {
                    code = Common.ResponseStatus.Success,
                    data = authUser
                };
            }
            catch (Exception ex)
            {
                var res = new AuthResponse<AuthUser>()
                {
                    code = Common.ResponseStatus.Fail,
                    msg = ex.Message
                };
                return res;
            }

        }


        /// <summary>
        /// 注销
        /// </summary>
        /// <returns></returns>
        public string Logout(string redirectUrl = null)
        {
            return this.logoutUrl(redirectUrl);
            //var client = new RestClient();
            //var request = new RestRequest(this.logoutUrl(), DataFormat.Json);
            //var res = client.Get(request);
            //this.CheckResponse(res.IsSuccessful, res.ErrorException);
        }
    }
}
